﻿// 801 有向图环判断.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//


/*
http://oj.daimayuan.top/course/14/problem/759


给你一张 n个顶点 m条边的有向简单图，顶点编号从 1到 n
，你需要判断这张图中是否存在环。

如果存在环，则输出 Yes，否则输出 No。

输入格式
第一行两个整数 n,m，表示图的顶点数和边数。

接下来 m行，每行两个整数 x,y
，表示 x号点到 y号点有一条有向边。

输出格式
输出一行一个字符串表示答案。

样例输入
4 4
1 2
2 3
3 4
1 4
样例输出
No
数据规模
对于所有数据，保证 2≤n≤10000,0≤m≤100000,1≤x,y≤n。
*/


#include <iostream>
#include <memory.h>
#include <queue>
#include <algorithm>

using namespace std;

const int N = 10010, M = 200010;
int n, m;                                   // 总点数
int h[N], w[M], e[M], ne[M], idx;           // 邻接表存储所有边
int dist[N], cnt[N];        // dist[x]存储1号点到x的最短距离，cnt[x]存储1到x的最短路中经过的点数
bool st[N];                 // 存储每个点是否在队列中


// 如果存在负环，则返回true，否则返回false。
bool spfa()
{
    // 不需要初始化dist数组
    // 原理：如果某条最短路径上有n个点（除了自己），那么加上自己之后一共有n+1个点，由抽屉原理一定有两个点相同，所以存在环。
    queue<int> q;
    for (int i = 1; i <= n; i++)
    {
        q.push(i);
        st[i] = true;
    }

    while (q.size())
    {
        auto t = q.front();
        q.pop();

        st[t] = false;

        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (dist[j] < dist[t] + w[i])
            {
                dist[j] = dist[t] + w[i];
                cnt[j] = cnt[t] + 1;
                if (cnt[j] >= n) return true;       // 如果从1号点到x的最短路中包含至少n个点（不包括自己），则说明存在环
                if (!st[j])
                {
                    q.push(j);
                    st[j] = true;
                }
            }
        }
    }

    return false;
}

void add(int a, int b, int c) {
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}

int main() {
    cin >> n >> m;
    memset(h, -1, sizeof h);
    for (int i = 0; i < m; i++) {
        int a, b; cin >> a >> b;
        add(a, b, 1);
    }

    if (spfa()) cout << "Yes" << endl;
    else cout << "No" << endl;

    return 0;
}